package pers.cz.postgirl.core.connect.simpledb;

import com.mysql.cj.jdbc.exceptions.MysqlDataTruncation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pers.cz.jefconfig.config.JefConfiguration;
import pers.cz.postgirl.core.connect.Connection;
import pers.cz.postgirl.core.enums.DbConfigItem;
import pers.cz.postgirl.core.store.LocalFileStore;
import pers.cz.postgirl.exception.ExceptionUtil;
import pers.cz.postgirl.util.TimeLag;

import javax.sql.DataSource;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @program: JefLogTail
 * @description: 数据库连接，
 * @author: Cheng Zhi
 * @create: 2023-03-05 13:35
 **/
public class DbConnnection extends Connection {

    Logger logger = LoggerFactory.getLogger(DbConnnection.class);

    private static final String DEFAULT_INSERT_SQL = "insert into postgirl.cz_test(test1,test2) values(?,?)";
    private static final String DEFAULT_SELECT_SQL = "select test2 as context from postgirl.cz_test where test1 = ?";

    private static final String IP_FINLENAME_INSERT_SQL = "insert into JEF_LOG_TAILA(ip, fileName, content) values(?, ?, ?)";

    java.sql.Connection connection;

    public DbConnnection(DataSource dataSource) {
        try {
            TimeLag timeLag = new TimeLag();
            // 由于使用的是druid管理数据库连接，所以这里不需要做单例
            connection = dataSource.getConnection();
            System.out.println("-------获取连接耗时：" + timeLag.cost());
        } catch (SQLException e) {
            ExceptionUtil.rethrow(e);
        }
    }

    @Override
    public void close() {
        try {
            connection.close();
        } catch (SQLException e) {
            ExceptionUtil.rethrow(e);
        }
    }

    @Override
    public void insert(String key, byte[] content) {
        PreparedStatement preparedStatement = null;
        String sql = JefConfiguration.get(DbConfigItem.DB_INSERT_SQL,DEFAULT_INSERT_SQL);
        try {
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, key);
            preparedStatement.setBytes(2, content);
            int count = preparedStatement.executeUpdate();
            if (count > 0) {
                logger.debug("保存成功" + count + "条");
            }
        } catch (SQLException e) {

            // 如果超长对象保存失败，则dump到本地文件中
            if (e instanceof MysqlDataTruncation) {
                LocalFileStore localFileStore = new LocalFileStore();
                localFileStore.set(key, content);

                logger.info("由于序列化后的数据太大，数据库不能完整保存，系统已自动转储到本地文件。");
            }

            logger.error("保存异常：", e);
        } finally {
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                    close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public String get(String key) {
        PreparedStatement preparedStatement = null;
        String sql = JefConfiguration.get(DbConfigItem.DB_INSERT_SQL,DEFAULT_SELECT_SQL);
        try {
            TimeLag timeLag = new TimeLag();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, key);
            ResultSet resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                String context = resultSet.getString("context");
                // 查询到一条即可
                return context;
            }

        } catch (SQLException e) {
            ExceptionUtil.rethrow(e);
        } finally {
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                    close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

        return "";
    }

    @Override
    public byte[] getBytes(String key) {

        PreparedStatement preparedStatement = null;
        String sql = JefConfiguration.get(DbConfigItem.DB_INSERT_SQL,DEFAULT_SELECT_SQL);
        try {
            TimeLag timeLag = new TimeLag();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, key);
            ResultSet resultSet = preparedStatement.executeQuery();
            System.out.println("----------------真正的执行耗时：" + timeLag.cost());
            while (resultSet.next()) {
                byte[] context = resultSet.getBytes("context");
                // 查询到一条即可
                return context;
            }

            // 如果走到这里还没有找到，则需要到本地文件中查找
            LocalFileStore store = new LocalFileStore();
            return store.getBytes(key);
        } catch (SQLException e) {
            ExceptionUtil.rethrow(e);
        } finally {
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                    close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

        return new byte[0];
    }

    @Override
    public Long autoIncrement(String key) {
        return null;
    }

    @Override
    public void expire(String key, Integer time) {

    }

    /**
     * 简单插入
     * @param content
     */
    @Override
    public void realInsert(String content) {
        PreparedStatement preparedStatement = null;
        String sql = JefConfiguration.get(DbConfigItem.DB_INSERT_SQL,DEFAULT_INSERT_SQL);
        try {
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, content);
            int count = preparedStatement.executeUpdate();
            if (count > 0) {
                logger.debug("保存成功" + count + "条");
            }
        } catch (SQLException e) {
            ExceptionUtil.rethrow(e);
        } finally {
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                    close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void realSet(String key, String value) {

    }

    /**
     * 指定字段插入
     * @param key
     * @param content
     */
    @Override
    public void realInsert(String key, String content) {
        PreparedStatement preparedStatement = null;
        String sql = JefConfiguration.get(DbConfigItem.DB_INSERT_SQL,DEFAULT_INSERT_SQL);
        try {
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, key);
            preparedStatement.setString(2, content);
            int count = preparedStatement.executeUpdate();
            if (count > 0) {
                logger.debug("保存成功" + count + "条");
            }
        } catch (SQLException e) {
            ExceptionUtil.rethrow(e);
        } finally {
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                    close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void realInsert(String ip, String fileName, String content) {
        PreparedStatement preparedStatement = null;
        String sql = JefConfiguration.get(DbConfigItem.DB_INSERT_SQL,IP_FINLENAME_INSERT_SQL);
        try {
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, ip);
            preparedStatement.setString(2, fileName);
            preparedStatement.setString(3, content);
            int count = preparedStatement.executeUpdate();
            if (count > 0) {
                logger.debug("保存成功" + count + "条");
            }
        } catch (SQLException e) {
            ExceptionUtil.rethrow(e);
        } finally {
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                    close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
